package com.web.controller;

import com.aliyuncs.exceptions.ClientException;
import com.web.annotation.LoginRequired;
import com.web.domain.Response;
import com.web.entity.UserInfo;
import com.web.utils.InviteCode;
import com.web.utils.MD5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

@Slf4j
@RestController
@RequestMapping(value = "/app")
public class LoginController extends BaseController{

    /**
     * 登录
     * @param phone
     * @param password
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/login")
    @ResponseBody
    @LoginRequired
    public Response Login(String phone,String password,String longitude,String latitude,String ipAddress) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(password) || StringUtils.isBlank(longitude) ||
                StringUtils.isBlank(latitude) || StringUtils.isBlank(ipAddress)){
            return Response.custom().failure("缺少必要参数!");
        }
        UserInfo info = findByUser("phone",phone);
        if (info == null){
            return Response.custom().failure("账号不存在!");
        }
        if (!info.getPassword().equals(MD5Util.EncoderByMd5(password))){
            return Response.custom().failure("账号或密码错误!");
        }
        //更新个人信息
        saveInfo(longitude,latitude,ipAddress);
        infoService.uploadUserInfo(info);
        //生成Token并返回
        String token = authenticationService.getToken(info);

        return Response.custom().ok().addParams(token);
    }

    /**
     * 注册
     * @param phone
     * @param password
     * @param vcode
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/register")
    @ResponseBody
    @LoginRequired
    public Response Register(String phone,String password,String vcode,String inviteCode) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(password) || StringUtils.isBlank(vcode)){
            return Response.custom().failure("缺少必要参数!");
        }
        UserInfo info = findByUser("phone",phone);
        if (info != null){
            return Response.custom().failure("账户已存在!");
        }
        String code = redisTemplate.opsForValue().get("1"+phone);
        if (vcode == null){
            return Response.custom().failure("验证码已失效!");
        }
        if (!vcode.equals(code)){
            return Response.custom().failure("验证码错误!");
        }

        //添加个人信息
        info = new UserInfo();
        info.setInviteCode(StringUtils.isNotBlank(inviteCode)?InviteCode.getInviteCodeLevel(getMarginInfo().getInviteCodeLength(),inviteCode
                ,getMarginInfo().getLevel()):InviteCode.getInviteCode(getMarginInfo().getInviteCodeLength()));
        info.setPhone(phone);
        info.setPassword(MD5Util.EncoderByMd5(password));
        infoService.addUser(info);
        info = null;
        info = findByUser("phone",phone);
        if (info == null){
            return Response.custom().failure("注册失败!");
        }
        //生成Token并返回
        String token = authenticationService.getToken(info);
        return Response.custom().ok().addParams(token);
    }




    /**
     * 微信登录
     * @param openid
     * @param longitude
     * @param latitude
     * @param ipAddress
     * @param jgId
     * @param type 1.微信登录2.QQ登录
     * @return
     */
    @PostMapping("/login/wechat")
    @ResponseBody
    @LoginRequired
    public Response LoginWechat(String openid,String longitude,String latitude,String ipAddress,String jgId,String type,String inviteCode){
        if (StringUtils.isBlank(openid) || StringUtils.isBlank(longitude) ||
                StringUtils.isBlank(latitude) || StringUtils.isBlank(ipAddress) || StringUtils.isBlank(jgId) || StringUtils.isBlank(type)){
            return Response.custom().failure("缺少必要参数");
        }
        UserInfo info = findByUser(type.equals("1")?"wx_id":"qq_id",openid);
        if (info == null){
            //注册
            info = saveInfo(longitude,latitude,ipAddress);
            info.setJgId(jgId);
            if (type.equals("1")){
                info.setWxId(openid);
            }else if (type.equals("2")){
                info.setQqId(openid);
            }
            info.setInviteCode(StringUtils.isNotBlank(inviteCode)?InviteCode.getInviteCodeLevel(getMarginInfo().getInviteCodeLength(),inviteCode,getMarginInfo().getLevel()):InviteCode.getInviteCode(getMarginInfo().getInviteCodeLength()));
            infoService.addUser(info);
            info = null;
            info = findByUser("wx_id",openid);
            if (info == null){
                return Response.custom().failure("注册失败!");
            }
        }else{
            //登录
            info = saveInfo(longitude,latitude,ipAddress);
            info.setJgId(jgId);
            infoService.uploadUserInfo(info);
            info = findByUser(type.equals("1")?"wx_id":"qq_id",openid);
            if (info == null){
                return Response.custom().failure("账号异常!");
            }
        }
        //生成Token并返回
        String token = authenticationService.getToken(info);
        return Response.custom().ok().addParams(token);
    }

    /**
     * 获取验证码
     * @param phone
     * @param type
     * @return
     */
    @PostMapping("/get/vcode")
    @ResponseBody
    @LoginRequired
    public Response getVcode(String phone,String type) throws ClientException {
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(type)){
            return Response.custom().failure("缺少必要参数");
        }
        switch (type){
            //注册
            case "1":
                if (findByUser("phone",phone) != null){
                    return Response.custom().failure("该账号已存在!");
                }
                if (!getVcodes(phone,type)){
                    return Response.custom().failure("验证码发送失败!");
                }
                return Response.custom().ok();
            //忘记密码
            case "2":
                if (findByUser("phone",phone) == null){
                    return Response.custom().failure("该账号不存在!");
                }
                if (!getVcodes(phone,type)){
                    return Response.custom().failure("验证码发送失败!");
                }
                return Response.custom().ok();
            //忘记密码
            case "3":
                if (findByUser("phone",phone) == null){
                    return Response.custom().failure("该账号不存在!");
                }
                if (!getVcodes(phone,type)){
                    return Response.custom().failure("验证码发送失败!");
                }
                return Response.custom().ok();
            default:
                return Response.custom().failure("类型不存在!");
        }
    }

    /**
     * 忘记密码
     * @param phone
     * @param newPwd
     * @param code
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/pwd/forget")
    @ResponseBody
    @LoginRequired
    public Response ForGetPwd(String phone,String newPwd,String code) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(newPwd) || StringUtils.isBlank(code)){
            return Response.custom().failure("缺少必要参数!");
        }
        String vcode = redisTemplate.opsForValue().get("2"+phone);
        if (vcode == null){
            return Response.custom().failure("验证码已失效!");
        }
        if (!vcode.equals(code)){
            return Response.custom().failure("验证码错误!");
        }
        UserInfo info = findByUser("phone",phone);
        if (info == null){
            return Response.custom().failure("该账号未注册!");
        }
        if (info.getPassword() == MD5Util.EncoderByMd5(newPwd)){
            return Response.custom().failure("旧密码不可与新密码相同!");
        }
        info.setPassword(MD5Util.EncoderByMd5(newPwd));
        infoService.uploadUserInfo(info);
        //生成Token并返回
        String token = authenticationService.getToken(info);
        return Response.custom().ok().addParams(token);
    }

    /**
     * 绑定手机号
     * @param phone
     * @param code
     * @param openid
     * @param type 1.微信绑定2.QQ绑定
     * @return
     */
    @PostMapping("/phone/bind")
    @ResponseBody
    @LoginRequired
    public Response BindPhone(String phone,String code,String openid,String type){
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(code) || StringUtils.isBlank(openid) || StringUtils.isBlank(type)){
            return Response.custom().failure("缺少必要参数!");
        }
        String vcode = redisTemplate.opsForValue().get("1"+phone);
        if (vcode == null){
            return Response.custom().failure("验证码已失效!");
        }
        if (!vcode.equals(code)){
            return Response.custom().failure("验证码错误!");
        }
        UserInfo info;
        switch (type){
            case "1":
                info = findByUser("wx_id",openid);
                break;
            case "2":
                info = findByUser("qq_id",openid);
                break;
            default:
                return Response.custom().failure("类型错误!");
        }
        if (info == null){
            return Response.custom().failure("该账号未注册!");
        }
        if (info.getPhone().equals(phone)){
            return Response.custom().failure("已经绑定过了!");
        }
        info.setPhone(phone);
        infoService.uploadUserInfo(info);
        return Response.custom().ok();
    }

    /**
     * 换绑手机号
     * @param oldPhone
     * @param newPhone
     * @param code
     * @return
     */
    @PostMapping("/phone/modify")
    @ResponseBody
    @LoginRequired
    public Response ModifyPhone(String oldPhone,String newPhone,String code){
        if (StringUtils.isBlank(oldPhone) || StringUtils.isBlank(newPhone) || StringUtils.isBlank(code)){
            return Response.custom().failure("缺少必要参数!");
        }
        String vcode = redisTemplate.opsForValue().get("1"+newPhone);
        if (vcode == null){
            return Response.custom().failure("验证码已失效!");
        }
        if (!vcode.equals(code)){
            return Response.custom().failure("验证码错误!");
        }

        UserInfo info = findByUser("phone",oldPhone);

        if (info == null){
            return Response.custom().failure("该账号未注册!");
        }
        if (oldPhone.equals(newPhone)){
            return Response.custom().failure("新手机号不可与旧手机号一致");
        }
        info.setPhone(newPhone);
        infoService.uploadUserInfo(info);
        return Response.custom().ok();
    }



    /**
     * 修改密码
     * @param phone
     * @param oldPwd
     * @param newPwd
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/pwd/modify")
    @ResponseBody
    @LoginRequired
    public Response ModifyPwd(String phone,String oldPwd,String newPwd) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(newPwd) || StringUtils.isBlank(oldPwd)){
            return Response.custom().failure("缺少必要参数!");
        }
        UserInfo info = findByUser("phone",phone);
        if (info == null){
            return Response.custom().failure("该账号未注册!");
        }
        if (!info.getPassword().equals(MD5Util.EncoderByMd5(oldPwd))){
            return Response.custom().failure("旧密码错误!");
        }
        if (oldPwd.equals(newPwd)){
            return Response.custom().failure("旧密码不可与新密码相同");
        }
        info.setPassword(MD5Util.EncoderByMd5(newPwd));
        infoService.uploadUserInfo(info);
        //生成Token并返回
        String token = authenticationService.getToken(info);
        return Response.custom().ok().addParams(token);
    }
    /**
     * 验证码核验
     * @param phone
     * @param type
     * @param code
     * @return
     */
    @PostMapping("/check/vcode")
    @ResponseBody
    @LoginRequired
    public Response checkVcode(String phone,String type,String code){
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(type) || StringUtils.isBlank(code)){
            return Response.custom().failure("缺少必要参数!");
        }
        String vcode = redisTemplate.opsForValue().get(type+phone);
        if (vcode == null){
            return Response.custom().failure("验证码已失效!");
        }
        if (!vcode.equals(code)){
            return Response.custom().failure("验证码错误!");
        }
        return Response.custom().ok();
    }

    /**
     * 保存登录必备信息
     * @param longitude
     * @param latitude
     * @param ipAddress
     * @return
     */
    public UserInfo saveInfo(String longitude,String latitude,String ipAddress){
        UserInfo info = new UserInfo();
        info.setLatitude(latitude);
        info.setLongitude(longitude);
        info.setIpAddress(ipAddress);
        info.setModifyTime(new Date());
        return info;
    }

}
